/*这里放置一些零碎的功能
 1.日志宏
 2.json序列化，反序列化
 3.uuid的实现
*/

#pragma once
#include <jsoncpp/json/json.h>
#include <iostream>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <sstream>
#include <random>
#include <memory>
#include <iomanip>
#include <atomic>

namespace qiangsir
{
#define LDBG 0
#define LINF 1
#define LERR 2
#define LDEFAULT LINF
// 日志宏
#define LOG(level, format, ...)                                                            \
    {                                                                                      \
        if (level >= 0)                                                                     \
        {                                                                                  \
            time_t t = time(NULL);                                                         \
            struct tm *curtime = localtime(&t);                                            \
            char strtime[32];                                                              \
            strftime(strtime, 31, "%m-%d %T", curtime);                                    \
            fprintf(stdout, "[%s][%s:%d] " format "\n", strtime, __FILE__, __LINE__, ##__VA_ARGS__); \
        }                                                                                  \
    }

#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__)
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__)
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__)

    class JSON
    {
    public:
        static bool Serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 实例化工厂
            Json::StreamWriterBuilder swb;
            swb["emitUTF8"] = true;

            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss);
            if (ret != 0)
            {
                std::cout << "write fail" << std::endl;
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool DeSerialize(const std::string &body, Json::Value &val)
        {
            Json::CharReaderBuilder crb;
            std::string errs;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false)
            {
                std::cout << "json unserialize failed : " << errs << std::endl;
                return false;
            }
            return true;
        }
    };

    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss;
            // 1.构建一个机器时间种子对象
            std::random_device rd;
            // 2.构建随机数对象(随机数引擎)
            std::mt19937 random(rd());
            // 3.控制范围字符
            std::uniform_int_distribution<int> dist(0, 255);
            // 4.输出8个随机数，组织成16进制字符串
            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << dist(random);
            }

            // 8字节序列号，采用原子累加
            static std::atomic<size_t> seq(1);
            // 叠加
            size_t cur = seq.fetch_add(1);
            // 组织为16进制,将一个整数与0xff相与，会保留该整数的最低8位（一个字节），高位都清零。
            ss << '-';
            for (int i = 7; i >= 0; i--)
            {
                if (i == 5)
                    ss << '-';
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0Xff);
            }
            return ss.str();
        }
    };
}